/**
 * Project Name:renshuaipeng-auth
 * File Name:LogAspect.java
 * Package Name:ren.renshuaipeng.auth.log
 * Date:2015年12月26日 上午11:23:51
 * Copyright (c) 2015, niao.shuai123@163.com All Rights Reserved.
 */

package ren.renshuaipeng.auth.web.log;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import ren.renshuaipeng.auth.common.AppContants;
import ren.renshuaipeng.auth.domain.auth.AuthUser;
import ren.renshuaipeng.auth.domain.auth.SysOprLog;
import ren.renshuaipeng.auth.service.auth.SysOprLogService;
import ren.renshuaipeng.util.DateUtil;
import ren.renshuaipeng.util.anno.log.OperatorLog;

/**
 * ClassName: LogAspect.java<br/>
 * Function: Log AOP. <br/>
 * Date: 2015年12月26日 上午11:23:51<br/>
 *
 * @author 任帅鹏（作者）
 * @version V1.00 （版本号）
 * @see
 * @since JDK 1.8
 */
@Aspect
@Component
public class LogAspect {
	@Autowired
	SysOprLogService sysOprLogService;

	// 本地异常日志记录对象
	private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

	@Pointcut("@annotation(ren.renshuaipeng.util.anno.log.OperatorLog)")
	public void serviceAspect() {
	}

	/**
	 * 注意：在Controller中必须带有public修饰符
	 * 
	 * @Name: controllerAspect
	 * @Description: TODO
	 * @Author 任帅鹏（作者）
	 * @Version V1.00 （版本号）
	 * @Create Date: 2015年12月26日 下午10:14:22（创建日期）
	 * @Parameters:
	 * @Return void
	 * @Throws
	 */
	@Pointcut("execution(* ren.renshuaipeng.auth.web.controller.*Controller.*(..)) && @annotation(ren.renshuaipeng.util.anno.log.OperatorLog)")
	public void controllerAspect() {
	}

	/**
	 * 前置通知 用于拦截Controller层记录用户的操作
	 * 
	 * @param joinPoint
	 *            切点
	 * @throws ClassNotFoundException
	 */
	@Before("controllerAspect()")
	public void doControllerBefore(JoinPoint joinPoint) {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		HttpSession session = request.getSession();
		// 读取session中的用户
		AuthUser user = (AuthUser) session.getAttribute(AppContants.LOGIN_SESSION);
		// 请求的IP TODO
		String ip = request.getRemoteAddr(); // Nginx 换方法

		SysOprLog sysOprLog = new SysOprLog();
		sysOprLog.setUserId(user == null ? "" : user.getId());
		sysOprLog.setUserName(user == null ? "" : user.getLoginName());
		sysOprLog.setLogIp(ip);
		sysOprLog.setCreateTime(DateUtil.getCurrentTime());
		try {
			Object[] data = getControllerMethodDescription(joinPoint);
			Integer logType = (Integer) data[0];
			String logInfo = data[1].toString();
			sysOprLog.setLogType(logType);
			sysOprLog.setLogInfo(logInfo);
			sysOprLogService.save(sysOprLog); // 此处考虑加异常日志
		} catch (Exception e) {
			logger.info("error", e.getMessage());
		}
	}

	/**
	 * 
	 * @Name: doAfterThrowing
	 * @Description: 异常通知 用于拦截service层记录异常日志
	 * @Author 任帅鹏（作者）
	 * @Version V1.00 （版本号）
	 * @Create Date: 2015年12月26日 下午12:01:02（创建日期）
	 * @Parameters: @param joinPoint
	 * @Parameters: @param e
	 * @Return void
	 * @Throws
	 */
	@AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
	public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
		// HttpServletRequest request = ((ServletRequestAttributes)
		// RequestContextHolder.getRequestAttributes())
		// .getRequest();
		// HttpSession session = request.getSession();
		// 读取session中的用户
		// AuthUser user = (AuthUser)
		// session.getAttribute(AppContants.LOGIN_SESSION);
		// // 获取请求ip
		// String ip = request.getRemoteAddr();
		// // 获取用户请求方法的参数并序列化为JSON格式字符串
		// String params = "";

		try {
			// if (joinPoint.getArgs() != null && joinPoint.getArgs().length >
			// 0) {
			// for (int i = 0; i < joinPoint.getArgs().length; i++) {
			// params += JSONUtils.obj2json(joinPoint.getArgs()[i]) + ";";
			// }
			// }
			/* ========控制台输出========= */
			// System.out.println("=====异常通知开始=====");
			// System.out.println("异常代码:" + e.getClass().getName());
			// System.out.println("异常信息:" + e.getMessage());
			// System.out.println("异常方法:"
			// + (joinPoint.getTarget().getClass().getName() + "." +
			// joinPoint.getSignature().getName() + "()"));
			// System.out.println("方法描述:" +
			// getServiceMthodDescription(joinPoint));
			// System.out.println("请求人:" + user.getLoginName());
			// System.out.println("请求IP:" + ip);
			// System.out.println("请求参数:" + params);
			/* ==========数据库日志========= */
			// Log log = SpringContextHolder.getBean("logxx");
			// log.setDescription(getServiceMthodDescription(joinPoint));
			// log.setExceptionCode(e.getClass().getName());
			// log.setType("1");
			// log.setExceptionDetail(e.getMessage());
			// log.setMethod(
			// (joinPoint.getTarget().getClass().getName() + "." +
			// joinPoint.getSignature().getName() + "()"));
			// log.setParams(params);
			// log.setCreateBy(user);
			// log.setCreateDate(DateUtil.getCurrentDate());
			// log.setRequestIp(ip);
			// 保存数据库
			// logService.add(log);
		} catch (Exception ex) {
			// 记录本地异常日志
			logger.error("异常通知异常信息:{}", ex.getMessage());
		}
		/* ==========记录本地异常日志========== */
		// logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}",
		// joinPoint.getTarget().getClass().getName() +
		// joinPoint.getSignature().getName(), e.getClass().getName(),
		// e.getMessage(), params);

	}

	/**
	 * @Name: getServiceMthodDescription
	 * @Description: 获取注解中对方法的描述信息 用于service层注解
	 * @Author 任帅鹏（作者）
	 * @Version V1.00 （版本号）
	 * @Create Date: 2015年12月26日 上午11:59:09（创建日期）
	 * @Parameters: @param joinPoint 切点
	 * @Parameters: @return 方法描述
	 * @Parameters: @throws Exception
	 * @Return String
	 * @Throws
	 */
	@SuppressWarnings("rawtypes")
	public static String getServiceMthodDescription(JoinPoint joinPoint) throws ClassNotFoundException {
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Class targetClass = Class.forName(targetName);
		Method[] methods = targetClass.getMethods();
		String description = "";
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					description = method.getAnnotation(OperatorLog.class).getInfo();
					break;
				}
			}
		}
		return description;
	}

	/**
	 * @Name: getControllerMethodDescription
	 * @Description: 获取注解中对方法的描述信息 用于Controller层注解
	 * @Author 任帅鹏（作者）
	 * @Version V1.00 （版本号）
	 * @Create Date: 2015年12月26日 上午11:59:37（创建日期）
	 * @Parameters: @param joinPoint 切点
	 * @Parameters: @return Object [] 方法描述
	 * @Parameters: @throws Exception
	 * @Return String
	 * @throws ClassNotFoundException
	 */
	@SuppressWarnings("rawtypes")
	public static Object[] getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
		Integer logType = 0;
		String logInfo = "";

		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Class targetClass = Class.forName(targetName);
		Method[] methods = targetClass.getMethods();

		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					logType = method.getAnnotation(OperatorLog.class).getType().getValue();
					logInfo = method.getAnnotation(OperatorLog.class).getInfo();
					break;
				}
			}
		}

		return new Object[] { logType, logInfo };
	}
}
